package com.ebo.upload;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.common.utils.IOUtils;
import com.alibaba.sdk.android.oss.model.CompleteMultipartUploadRequest;
import com.alibaba.sdk.android.oss.model.CompleteMultipartUploadResult;
import com.alibaba.sdk.android.oss.model.InitiateMultipartUploadRequest;
import com.alibaba.sdk.android.oss.model.InitiateMultipartUploadResult;
import com.alibaba.sdk.android.oss.model.ListPartsRequest;
import com.alibaba.sdk.android.oss.model.ListPartsResult;
import com.alibaba.sdk.android.oss.model.PartETag;
import com.alibaba.sdk.android.oss.model.PartSummary;
import com.alibaba.sdk.android.oss.model.UploadPartRequest;
import com.alibaba.sdk.android.oss.model.UploadPartResult;
import com.ebo.agora.openvcall.AGApplication;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import io.agora.openvcall.R;
import utils.Lg;
import utils.Pub;

/**
 * Created by zhouzhuo on 12/4/15.
 */
public class MultipartUpload {
    private static final String endpoint = "http://oss-cn-shanghai.aliyuncs.com";
    private static final String accessKeyId = "LTAIkU5limp8uTGK";
    private static final String accessKeySecret = "oDNUO7MsVHtQGDLeIvUTNYglnEnybu";
    private static final String Bucket = "cbzrjmmv";
    private static OSS oss;
    private String testBucket;
    public String nameObject="";
    private String uploadFilePath;
    public long size_Max;
    public long size_Finished;
    public int progress;
//    public MultipartUpload(OSS client, String testBucket, String , String uploadFilePath) {
//        initConfig();
//        this.oss = client;
//        this.testBucket = testBucket;
//        this.nameObject =  ;
//        this.uploadFilePath = uploadFilePath;
//        isPause = false;
//    }
//progressListener listener;
    public MultipartUpload( String uploadFilePath) {
        initConfig();
//        this.oss = client;
        this.testBucket = Bucket;
        this.nameObject =getObjectKey(uploadFilePath);
        this.uploadFilePath = uploadFilePath;
        isPause = false;
//        this.listener = listener;
    }
    private static boolean hasInited=false;
    void initConfig() {
        if(hasInited){
            return;
        }
        hasInited=true;
        OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // 连接超时，默认15秒
        conf.setSocketTimeout(15 * 1000); // socket超时，默认15秒
        conf.setMaxConcurrentRequest(5); // 最大并发请求书，默认5个
        conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次
        OSSLog.enableLog();
        oss = new OSSClient(AGApplication.getInstance(), endpoint, credentialProvider, conf);
    }

    private static String getObjectKey(String filepath) {
//        Lg.d("filepath=" + filepath + ",value=" + Pub.readValue(filepath));
        String fileName = Pub.readValue(filepath);
//        Lg.d("fileName = " + fileName);
        if (!TextUtils.isEmpty(fileName)) {
            return fileName;
        }
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String str = sdf.format(date);
        Random r = new Random();
        int i = r.nextInt(9999);
        StringBuffer sb = new StringBuffer();
        String extension = filepath.substring(filepath.lastIndexOf(".") + 1);
        //年月日
        sb.append(str);
        //4位随机数
        sb.append(i);
        //后缀名
        sb.append(".");
        sb.append(extension);
        Pub.saveValue(filepath, sb.toString());
//        Lg.d("Pub.saveValue filepath=" + filepath + ",sb.toString()=" + sb.toString());
        return sb.toString();
    }






    private long partLength = 0;//一个分片的大小
    //获取已上传的parts
    private List<PartSummary> getResumableParts() {
        //传入Object名称，返回：上次记录的没有上传完毕的uploadid
        String uploadID = Pub.readValue(nameObject);
        if (!TextUtils.isEmpty(uploadID)) {
            ListPartsRequest listParts = new ListPartsRequest(testBucket, nameObject, uploadID);
            ListPartsResult result = null;
            try {
                result = oss.listParts(listParts);
            } catch (ClientException e) {
                e.printStackTrace();
            } catch (ServiceException e) {
                e.printStackTrace();
            }
            return result.getParts();
        }
        return null;
    }

    private boolean isPause;

    public void pause() {
        isPause = true;
    }

    public void resume() {
        isPause = false;
    }

    public boolean isPause() {
        return isPause;
    }


    int currentIndex;
    private static final long partSize = 128 * 1024;
    String uploadId;

    public void multipartUpload() throws ClientException, ServiceException, IOException {
        String uploadID = Pub.readValue(nameObject);
        if (!TextUtils.isEmpty(uploadID)) {
            //断点续传
            multipartUploadResume();
        } else {
            //从头上传
            multipartUploadFirst();
        }
    }

    public void multipartUploadResume() throws ClientException, ServiceException, IOException {
        currentIndex = 1;
        partLength = 0;

        List<PartSummary> listParts = getResumableParts();
        if (listParts != null) {
            if (listParts.size() > 0) {
                //可断点续传
                currentIndex = listParts.size() + 1;
                partLength = listParts.get(0).getSize();
//                Lg.d("currentIndex-1 = " + (currentIndex - 1) + ",tag = " + listParts.get(listParts.size() - 1).getETag());
            }
        }

        uploadId = Pub.readValue(nameObject);



        File uploadFile = new File(uploadFilePath);
        InputStream input = new FileInputStream(uploadFile);
        size_Max = uploadFile.length();


        size_Finished =  partLength * (currentIndex - 1);//断点续传已完成的进度

        //跳过已上传的分片
        for(int i=0;i<currentIndex-1;i++)
        {
            int partLength = (int) Math.min(partSize, size_Max - size_Finished);
             IOUtils.readStreamAsBytesArray(input, partLength);
        }

        while (size_Finished < size_Max) {
            //暂停/继续boolean值
            if (!isPause) {
                int partLength = (int) Math.min(partSize, size_Max - size_Finished);
                byte[] partData = IOUtils.readStreamAsBytesArray(input, partLength);
                UploadPartRequest uploadPart = new UploadPartRequest(testBucket, nameObject, uploadId, currentIndex);
                uploadPart.setPartContent(partData);
                UploadPartResult uploadPartResult = oss.uploadPart(uploadPart);
                size_Finished += partLength;
//                Lg.d("currentIndex=" + currentIndex + ",uploadedLength = " + uploadedLength + ",fileLength=" + fileLength + ",ETag = " + uploadPartResult.getETag());
                currentIndex++;
                progress = (int) (size_Finished * 100 / size_Max);
//                listener.onChange(size_Max,size_Finished,progress);
//                if (currentIndex % 2 == 1) {
//                    sendBroadCast(AGApplication.getInstance().getResources().getInteger(R.integer.broadcast_upload_onProgress), progress);
//                }
            }
        }

        List<PartETag> partETags = new ArrayList<PartETag>();
        List<PartSummary> list = getResumableParts();
        for (int i = 0; i < list.size(); i++) {
            PartETag pt = new PartETag(i + 1, list.get(i).getETag());
            partETags.add(pt);
//            Lg.d("partETags Number = " + pt.getPartNumber() + ",partETags ETag =" + pt.getETag());
        }
        CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(testBucket, nameObject, uploadId, partETags);
        CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);


        Lg.d("multipart upload success! Location: " + completeResult.getLocation());
        Pub.delValue(uploadFilePath);
        Pub.delValue(nameObject);
//        listener.onChange(size_Max,size_Finished,100);
//        sendBroadCast(AGApplication.getInstance().getResources().getInteger(R.integer.broadcast_upload_success), 100);
    }

    public void multipartUploadFirst() throws ClientException, ServiceException, IOException {
        currentIndex = 1;
        partLength = 0;
        //从头上传
        {
            InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest(testBucket, nameObject);
            InitiateMultipartUploadResult initResult = oss.initMultipartUpload(init);
            //以key-value形式保存Object uploadId，用于下次断点续传
            uploadId = initResult.getUploadId();
            Pub.saveValue(nameObject, uploadId);
        }

        //以下代码基本和官网例子一致===============
        File uploadFile = new File(uploadFilePath);
        InputStream input = new FileInputStream(uploadFile);
        size_Max = uploadFile.length();
        size_Finished = 0;//断点续传已完成的进度
        List<PartETag> partETags = new ArrayList<PartETag>();
        while (size_Finished < size_Max) {
            //暂停/继续boolean值
            if (!isPause) {
                int partLength = (int) Math.min(partSize, size_Max - size_Finished);
                byte[] partData = IOUtils.readStreamAsBytesArray(input, partLength);
                UploadPartRequest uploadPart = new UploadPartRequest(testBucket, nameObject, uploadId, currentIndex);
                uploadPart.setPartContent(partData);
                UploadPartResult uploadPartResult = oss.uploadPart(uploadPart);
                partETags.add(new PartETag(currentIndex, uploadPartResult.getETag()));
                size_Finished += partLength;
//                Lg.d("currentIndex=" + currentIndex + ",uploadedLength = " + uploadedLength + ",fileLength=" + fileLength + ",ETag = " + uploadPartResult.getETag());
                currentIndex++;
                progress = (int) (size_Finished * 100 / size_Max);
//                listener.onChange(size_Max,size_Finished,progress);
//                if (currentIndex % 2 == 1) {
//                    sendBroadCast(AGApplication.getInstance().getResources().getInteger(R.integer.broadcast_upload_onProgress), progress);
//                }
            }
        }

        CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest(testBucket, nameObject, uploadId, partETags);
        CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
        Lg.d("multipart upload success! Location: " + completeResult.getLocation());
        Pub.delValue(uploadFilePath);
        Pub.delValue(nameObject);
//        listener.onChange(size_Max,size_Finished,100);
//        sendBroadCast(AGApplication.getInstance().getResources().getInteger(R.integer.broadcast_upload_success), 100);
    }

    void sendBroadCast(int state, int Progress) {
        Intent intent = new Intent();
        intent.setAction(AGApplication.getInstance().getResources().getString(R.string.broadcast_upload));
        Bundle bundle = new Bundle();
        bundle.putInt(AGApplication.getInstance().getResources().getString(R.string.broadcast_upload_state), state);
        bundle.putInt(AGApplication.getInstance().getResources().getString(R.string.broadcast_upload_progressNumber), Progress);
        bundle.putString("object", nameObject);
        intent.putExtras(bundle);
        AGApplication.getInstance().sendBroadcast(intent);
    }

//    interface progressListener{
//        void onChange(long sizeMax,long sizeFinished,int progress);
//    }

}
